<?php
/**
* pandarouter
* @author panda
**/
  define("WEBPATH","http://localhost/app/pandarouter/");
  define("TIMEOUT",4); //读取返回数据超时 单位:秒
  define("REQUESTSFOLDER","requests");
  define("CACHEFOLDER","cache");
  define("DS", DIRECTORY_SEPARATOR);
  define("BROWSE",$_SERVER['SCRIPT_NAME']);

 

  set_time_limit(TIMEOUT);
  $pandarouter = new PandaRouter();
  $pandarouter->parse()->work();

  class PandaRouter {
    private $data;
    /**
    * type 1:request from webbrower client 2:request from java client 3:data from java client
    **/
    private $requstFile = "";
    private $type;
    private $timeout = TIMEOUT; // ms
    private $localUrl = "";
    private $queryPath = "";

    function __construct(){
      $this->data['get'] = $_GET;
      $this->data['post'] = $_POST;
    }
    function saveRequestToLocal(){
      $id = md5(microtime().$this->queryPath.rand(1,99999));
      $this->requstFile = REQUESTSFOLDER.DS.$id;
      $request = "id:".$id."\r\n";
      $request .= "url:".$this->queryPath."\r\n";
      file_put_contents($this->requstFile, $request);
    }
    function parse(){
      $this->type = isset($this->data['post']['pandarouter_data'])?$this->data['post']['pandarouter_type']:1;
      $this->queryPath = isset($this->data['get']['u'])?$this->data['get']['u']:"";
      return $this;
    }
    //输出结果到浏览器
    function response($data){
      $arr = split("\r\n", $data);
      $result = "";
      foreach ($arr as $k => $v) {
        if(substr($v,0,5)=="body:")
          echo pathParser(base64_decode(substr($v, 5)));
        if(substr($v,0,5)=="type:")
          header("Content-Type:".substr($v, 5));
        if(substr($v,0,13)=="lastModified:") {
          header("Last-Modified:".substr($v, 13));
          file_put_contents(CACHEFOLDER.DS.md5($this->queryPath), substr($v, 13));
        }
      }
    }
    function checkRequest(){
      //检查缓存
      if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])){
        if(file_exists(CACHEFOLDER.DS.md5($this->queryPath)) && file_get_contents(CACHEFOLDER.DS.md5($this->queryPath)) == $_SERVER['HTTP_IF_MODIFIED_SINCE'])
          if(!((isset($_SERVER['HTTP_PRAGMA']) && $_SERVER['HTTP_PRAGMA']=="no-cache") || (isset($_SERVER['HTTP_CACHE_CONTROL']) && $_SERVER['HTTP_CACHE_CONTROL']=="no-cache"))){
            header("HTTP/1.1 304 Not Modified");
            exit;
          }
      }

    }
    function work(){
      $this->checkRequest();
      if($this->type == 1) {
        $this->saveRequestToLocal();
        /**
        * 循环测试数据是否返回
        **/
        $elapsed = 0;
        while($elapsed<$this->timeout){
          if(!file_exists($this->requstFile)) {
            if(file_exists($this->requstFile."-1")) {
              $result = file_get_contents($this->requstFile."-1");
              $this->response($result);
              unlink($this->requstFile."-1");
              exit;
            }
          }
          $elapsed++;
          sleep(1);
        }
        echo "error 访问超时";
      }else if($this->type==2) {
        $dir = $this->scandir(REQUESTSFOLDER);
        if(count($dir)>0) {
          $body = file_get_contents(REQUESTSFOLDER.DS.$dir[0]);
          rename(REQUESTSFOLDER.DS.$dir[0] , REQUESTSFOLDER.DS.$dir[0]."-0");
          echo $body;
          exit;
        }else
        exit('0');
      }else {
        $reqid = $this->data['post']['pandarouter_reqid'];
        if(file_exists(REQUESTSFOLDER.DS.$reqid."-0")) {
          $this->localUrl = $this->data['post']['pandarouter_localurl'];
          file_put_contents(REQUESTSFOLDER.DS.$reqid."-0", $this->data['post']['pandarouter_data']);
          rename(REQUESTSFOLDER.DS.$reqid."-0",REQUESTSFOLDER.DS.$reqid."-1");
        }
        echo "1";
      }
    }

    private function scandir($path) {
      $files = array();
      $tmp = array();
      if(function_exists("scandir")&&false) {
        $tmp = scandir($path);
      }else{
        $reqdir = dir($path);
        while($tmp[] = $reqdir->read()){}
      }
      foreach ($tmp as $k => $v)
        if($v != "." && $v != ".." && $v !="" && strpos($v, "-")==false)
          $files[] = $v;
        return $files;
      }
    }

    function pathParser($body){
      $body = preg_replace_callback('#(?><[A-Z0-9]{1,15})(?>\s+[^>\s]+)*?\s*(?>(href|src|background|poster)\s*=(?!\\\\)\s*)(?>([\\\'"])?)((?(2)(?(?<=")[^"]{1,2048}|[^\\\']{1,2048})|[^ >]{1,2048}))(?(2)\\2|)#i', 
        function ($input) {
          $flag = stripos($input[0], 'iframe') === 1 ? 'frame' : '';
          return str_replace($input[3], htmlspecialchars(proxyURL(htmlspecialchars_decode($input[3]), $flag)), $input[0]);
        }
        , $body);
      return $body;
    }

    function proxyURL($url, $givenFlag = false) {
      global $CONFIG, $options, $bitfield, $flag;

  # Remove excess whitespace
      $url = trim($url);

  # check for binary images
      if (stripos($url,'data:image')===0) {
        return $url;
      }

  # handle javascript
      if (stripos($url,'javascript:')===0 || stripos($url,'livescript:')===0) {
  # return JS($url);
        return '';
      }

  # Validate the input
      if ( empty($url) || $url[0]=='#' || $url=='about:' || stripos($url,'data:')===0 || stripos($url,'file:')===0 || stripos($url,'res:')===0 || stripos($url,'C:')===0 || strpos($url, BROWSE)===0 ) {
        return '';
      }

  # Extract any #anchor since we don't want to encode that
      if ( $tmp = strpos($url, '#') ) {
        $anchor = substr($url, $tmp);
        $url = substr($url, 0, $tmp);
      } else {
        $anchor = '';
      }

  # Convert to absolute URL (if not already)
      $url = absoluteURL($url);

  # Add encoding
      if ( $options['encodeURL'] ) {

    # Part of our encoding is to remove HTTP (saves space and helps avoid detection)
        $url = substr($url, 4);

    # Encrypt
        if ( isset($GLOBALS['unique_salt']) ) {
          $url = arcfour('encrypt',$GLOBALS['unique_salt'],$url);
        }
      }

  # Protect chars that have other meaning in URLs
      $url = rawurlencode($url);

  # Determine flag to use - $givenFlag is passed into function, $flag
  # is global flag currently in use (used here for persisting the frame state)
      $addFlag = $givenFlag ? $givenFlag : ( $flag == 'frame' ? 'frame' : '' );

  # Return in path info format (only when encoding is on)
      if ( $CONFIG['path_info_urls'] && $options['encodeURL'] ) {
        return BROWSE . '/' . str_replace('%', '_', chunk_split($url, 8, '/')) . 'b' . $bitfield . '/' . ( $addFlag ? 'f' . $addFlag : '') . $anchor;
      }

  # Otherwise, return in 'normal' (query string) format
      return BROWSE . '?u=' . $url . '&b=' . $bitfield . ( $addFlag ? '&f=' . $addFlag : '' ) . $anchor;
    }


function absoluteURL($input) {
  global $base, $URL;

  # Check we have something to work with
  if ( $input == false ) {
    return $input;
  }

  # "//domain.com" is valid - add the HTTP protocol if we have this
  if ( $input[0] == '/' && isset($input[1]) && $input[1] == '/' ) {
    $input= $URL['scheme'].':'.$input;
  }

  # URIs that start with ? are relative to the page loaded
  if ($input[0] == '?') {
    $input = $URL['href'].$input;
  }

  # Look for http or https and if necessary, convert relative to absolute
  if ( stripos($input, 'http://') !== 0 && stripos($input, 'https://') !== 0 ) {

    # . refers to current directory so do nothing if we find it
    if ( $input == '.' ) {
      $input = '';
    }

    # Check for the first char indicating the URL is relative from root,
    # in which case we just need to add the hostname prefix
    if ( $input && $input[0] == '/' ) {
      $input = $URL['scheme_host'] . $input;
    } else if ( isset($base) ) {

      # Not relative from root, is there a base href specified?
      $input = $base . $input;

    } else {

      # Not relative from root, no base href, must be relative to current directory
      $input = $URL['scheme_host'] . $URL['path'] . $input;

    }
  }

  # URL is absolute. Now attempt to simplify path.   
  # Strip ./ (refers to current directory)
  $input = str_replace('/./', '/', $input);

  # Strip double slash #
  if ( isset($input[8]) && strpos($input, '//', 8) ) {
  # $input = preg_replace('#(?<!:)//#', '/', $input);
  }

  # Look for ../
  if ( strpos($input, '../') ) {

    # Extract path component only
    $oldPath = 
    $path   = parse_url($input, PHP_URL_PATH);

    # Convert ../ into "go up a directory"
    while ( ( $tmp = strpos($path, '/../') ) !== false ) {

      # If found at start of path, simply remove since we can't go
      # up beyond the root.
      if ( $tmp === 0 ) {
        $path = substr($path, 3);
        continue;
      }

      # It was found later so find the previous /
      $previousDir = strrpos($path, '/', - ( strlen($path) - $tmp + 1 ) );

      # And splice that directory out
      $path = substr_replace($path, '', $previousDir, $tmp+3-$previousDir);

    }

    # Replace path component with new
    $input = str_replace($oldPath, $path, $input);

  }

  return $input;

}

    ?>